// Package wpcfg 配置封装
// 通过go-config实现
package wpcfg

import (
	"fmt"
	"strings"

	"github.com/micro/go-micro/config"
	"github.com/micro/go-micro/config/reader"
	"github.com/micro/go-micro/config/source/file"

	cst "gamesdk/wanyu/server/engine/globaldef/consts"
	"gamesdk/wanyu/server/engine/utils"
)

var (
	localConfigDir string
	configs        = make(map[cst.ConfigType]config.Config)
)

func init() {
	localConfigDir = utils.GetCurDir()
}

// 配置错误接口处理
type configError struct {
	tag cst.ConfigType
	msg string
}

func (e *configError) Error() string {
	return fmt.Sprintf("%d %s", e.tag, e.msg)
}

//Bytes 返回json原始数据
func Bytes(tag cst.ConfigType) ([]byte, error) {
	cfg, ok := configs[tag]
	if !ok {
		return nil, &configError{tag, "data does not exist!"}
	}
	return cfg.Bytes(), nil
}

//Map 返回map数据
func Map(tag cst.ConfigType) (map[string]interface{}, error) {
	cfg, ok := configs[tag]
	if !ok {
		return nil, &configError{tag, "data does not exist!"}
	}
	return cfg.Map(), nil
}

//Scan 读值到go类型
func Scan(tag cst.ConfigType, v interface{}) error {
	cfg, ok := configs[tag]
	if !ok {
		return &configError{tag, "data does not exist!"}
	}
	return cfg.Scan(v)
}

//ScanNode 读值子节点数据到go类型
func ScanNode(tag cst.ConfigType, v interface{}, path ...string) error {
	var value reader.Value
	var err error
	if value, err = Get(tag, path...); err != nil {
		return err
	}
	return value.Scan(v)
}

//Sync 强迫同步
func Sync(tag cst.ConfigType) error {
	cfg, ok := configs[tag]
	if !ok {
		return &configError{tag, "data does not exist!"}
	}
	return cfg.Sync()
}

//Get 从数据中得到一个值
func Get(tag cst.ConfigType, path ...string) (reader.Value, error) {
	cfg, ok := configs[tag]
	if !ok {
		return nil, &configError{tag, "data does not exist!"}
	}
	return cfg.Get(path...), nil
}

//LoadFile 从本地装载一个文件
func LoadFile(tag cst.ConfigType, path string) (config.Config, error) {
	index := strings.IndexByte(path, '.')
	if index < 0 {
		path += cst.CDSN
	}
	cfg, ok := configs[tag]
	if ok {
		return cfg, nil
	}

	cfg = config.NewConfig()
	if erro := cfg.Load(file.NewSource(file.WithPath(path))); erro != nil {
		return nil, erro
	}
	configs[tag] = cfg
	return cfg, nil
}

//SyncLoadFile 强制同步装在配置数据
func SyncLoadFile(tag cst.ConfigType, path string) (config.Config, error) {
	cfg, err := LoadFile(tag, path)
	if err != nil {
		return nil, err
	}
	cfg.Sync()
	return cfg, nil
}
